﻿using System;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Data;
using System.Collections;
using System.IO;
/*
namespace ErpServer
{
    public delegate void ShowTextCallback(string s);
    public delegate void BindCallback();
    public delegate void RemoveEventHandler(string userName);
    public delegate void WriteLogCallback(int id, string name, string remoteEndPoint, string detail);

    public class ListenConnection
    {
        #region  数据成员

        /// <summary>
        /// 状态等待位，用来监听新的连接
        /// </summary>
        private static ManualResetEvent allDone = new ManualResetEvent(false);

        /// <summary>
        /// 监听线程
        /// </summary>
        public static Thread listenThread = new Thread(new ThreadStart(Listen));

        /// <summary>
        /// 定义主窗体中显示文本的事件
        /// </summary>
        internal static event ShowTextCallback ShowText;

        /// <summary>
        /// 定义显示连接信息的事件
        /// </summary>
        internal static event BindCallback Bind;

        /// <summary>
        /// 维持连接信息的数组
        /// </summary>
        internal static Clients clients = new Clients();

        /// <summary>
        /// 维持连接信息的表
        /// </summary>
        public static DataTable dt = new DataTable();

        /// <summary>
        /// 监听Socket
        /// </summary>
        private static Socket listener;

        /// <summary>
        /// 定义一个委托实例，当某个连接线程Socket异常时清除它
        /// </summary>
        public static RemoveEventHandler remove = new RemoveEventHandler(RemoveByUserName);

        /// <summary>
        /// 错误登录列表
        /// </summary>
        public static ArrayList errorLogin = new ArrayList();

        #endregion

        /// <summary>
        /// 监听函数
        /// </summary>
        public static void Listen()
        {
            //先测试是否能连接到数据库
            ShowText("正在连接到数据库……\r\n");
            try
            {
                (new DBConnection()).GetConnection().Open();
            }
            catch (Exception)
            {
                ShowText("连接数据库失败！\r\n");
                return;
            }
            ShowText("连接数据库成功！\r\n");
            try
            {
                string HostName = Dns.GetHostName(); //得到主机名
                IPHostEntry IpEntry = Dns.GetHostEntry(HostName); //得到主机IP
                IPAddress[] addrs = IpEntry.AddressList;
                IPAddress ipAddress = null;
                foreach (IPAddress ip in addrs)
                {
                    if (ip.AddressFamily == AddressFamily.InterNetwork)
                    {
                        ipAddress = IPAddress.Parse(ip.ToString());
                    }
                }
                IPEndPoint localEndPoint = new IPEndPoint(ipAddress, Properties.Settings.Default.ListenPort);

                // 生成一个TCP的socket
                listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                listener.Bind(localEndPoint);

                listener.Listen(Properties.Settings.Default.ConnectionNumber);
                ShowText("开始监听……\r\n");

                while (true)
                {
                    // Set the event to nonsignaled state.
                    allDone.Reset();

                    //开启异步监听socket
                    listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);

                    // 让程序等待，直到连接任务完成。在AcceptCallback里的适当位置放置allDone.Set()语句.
                    allDone.WaitOne();
                }

            }
            catch (SocketException e)
            {
                ShowText("Exception: " + e.ToString() + "\r\n");
            }
            catch (ObjectDisposedException)
            {
                return;
            }
        }

        /// <summary>
        /// 当有客户端连接请求后调用此回调函数
        /// </summary>
        /// <param name="ar"></param>
        private static void AcceptCallback(IAsyncResult ar)
        {
            try
            {
                // 添加此命令，让主线程继续.
                allDone.Set();

                // 获取客户请求的socket
                Socket listener = (Socket)ar.AsyncState;
                Socket handler = listener.EndAccept(ar);

                ShowText("新连接，连接来自" + handler.RemoteEndPoint + "\r\n");

                // 造一个容器，并用于接收命令.
                StateObject state = new StateObject();
                state.workSocket = handler;
                handler.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReadCallback), state);
            }
            catch (Exception)
            {
                return;
            }
        }

        /// <summary>
        /// 处理登录请求，成功则开启新线程
        /// </summary>
        /// <param name="ar"></param>
        private static void ReadCallback(IAsyncResult ar)
        {
            // 从异步currentConn对象中获取currentConn和socket对象.
            StateObject state = (StateObject)ar.AsyncState;
            Socket handler = state.workSocket;
            try
            {
                // 从客户端socket读取数据.  
                int bytesRead = handler.EndReceive(ar);
                string number = Encoding.ASCII.GetString(state.buffer, 8, 4);
                string content = Encoding.Unicode.GetString(state.buffer, 12, bytesRead - 12);
                content = DES.DecryptDES(content, "12345678");
                ShowText("From " + state.workSocket.RemoteEndPoint + ": " + number + "---" + content + "\r\n");
                string[] str = content.Split('|');
                if (number == "1020")   //检查客户端是否需要更新并提供更新服务
                {
                    if (Convert.ToInt32(str[0]) >= Properties.Settings.Default.ClientVersion)
                    {
                        Send(handler, "1021");       //客户端为最新版本，无需更新
                        handler.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReadCallback), state);
                        return;
                    }
                    else
                    {
                        Send(handler, "1022");       //客户端是低版本，需要更新
                        handler.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReadCallback), state);
                        return;
                    }
                }
                else if (number == "1030")          //处理更新请求
                {
                    string[] paths = GetUpdateFilePath(str[0]);
                    if (paths == null)        //如果没有可更新的文件
                    {
                        Send(handler, "1031", Properties.Settings.Default.ClientVersion.ToString());
                        handler.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReadCallback), state);
                        return;
                    }
                    else                      //如果客户端需要更新
                    {
                        string paths_info = "";
                        long len = 0;
                        string path = Directory.GetCurrentDirectory();
                        FileInfo f;
                        for (int i = 0; i < paths.Length; i++)
                        {
                            paths_info += paths[i] + "|";
                            f = new FileInfo(path + "\\ClientReleaseFiles\\" + paths[i]);
                            len += f.Length;
                        }
                        Send(handler, "1032", paths_info + len.ToString());

                        for (int i = 0; i < paths.Length; i++)
                        {
                            Thread.Sleep(1000);
                            FileStream file = new FileStream(path + "\\ClientReleaseFiles\\" + paths[i], FileMode.Open, FileAccess.Read);
                            BinaryReader binaryreader = new BinaryReader(file);
                            byte[] file_data = new byte[4098];
                            int dataByte;
                            long file_length = file.Length + 4;
                            byte[] send_length_number = new byte[12];
                            byte[] send_num = Encoding.ASCII.GetBytes("1033");
                            for (int j = 0; j < 8; j++)
                            {
                                send_length_number[j] = (byte)(file_length % 256);
                                file_length = file_length >> 8;
                            }
                            for (int j = 0; j < 4; j++)
                            {
                                send_length_number[j + 8] = send_num[j];
                            }
                            handler.Send(send_length_number);
                            while ((dataByte = binaryreader.Read(file_data, 0, 4098)) != 0)                 //这个注意是将文件写成流的形式
                            {
                                handler.Send(file_data, dataByte, SocketFlags.None);           //发送文件流到目标机器
                            }
                            binaryreader.Close();
                            file.Close();
                        }

                        Send(handler, "1034", Properties.Settings.Default.ClientVersion.ToString());

                        handler.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReadCallback), state);
                        return;
                    }
                }
                if (number != "1000")         //如果不是登录请求
                {
                    string sql = "insert into tb_Alarm(IPEndPoint,Title,Detail) values('" + handler.RemoteEndPoint + "','登录异常','" + content + "')";
                    (new DBConnection()).ExecuteSql(sql);
                    return;
                }
                if (FindErrorLoginTimes(str[0]) >= 3)        //如果三分钟内错误登录三次以上
                {
                    Send(handler, "1003", "连续错误三次，请您三分钟后再登录！");
                    handler.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReadCallback), state);
                    return;
                }
                if (UserLogin.LoginCheck(str[0], str[1]) == true)      //如果登录成功
                {
                    ReLoginCheck(str[0]);        //检查重复登录并解决
                    DBConnection db = new DBConnection();
                    string sql = "select AdminLevel from tb_Admin where AdminName='" + str[0] + "'";
                    string userLevel = db.GetString(sql);
                    Send(handler, "1001", userLevel);
                    int index = clients.Add(new Client(handler, str[0], Convert.ToInt32(userLevel)));
                    clients[index].ClientThread.Start();
                    Bind();
                }
                else
                {
                    errorLogin.Add(new ErrorLogin(str[0], DateTime.Now));
                    Send(handler, "1002", "用户名或密码错误!");      //用户名或密码错误
                    handler.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReadCallback), state);
                }
            }
            catch (Exception)
            {
                return;
            }
        }

        /// <summary>
        /// 检查重复登录并迫使旧的客户端下线
        /// </summary>
        /// <param name="str">登录名</param>
        private static void ReLoginCheck(string str)
        {
            for (int i = 0; i < clients.Count; i++)
            {
                if (clients[i].UserName == str)
                {
                    Send(clients[i].WorkSock, "1004", "被迫下线，您的帐号在其他地址登录了!");
                    Thread.Sleep(500);
                    clients.RemoveAt(i);
                    return;
                }
            }
        }

        /// <summary>
        /// 用指定Socket向客户端发送字符串
        /// </summary>
        /// <param name="handler">Socket</param>
        /// <param name="number">数据类型代码</param>
        private static void Send(Socket handler, string number)
        {
            ShowText("To " + handler.RemoteEndPoint + ": " + number + "---\r\n");
            byte[] send_data = new byte[12];
            byte[] send_num = Encoding.ASCII.GetBytes(number);
            for (int i = 0; i < 8; i++)
            {
                send_data[i] = 0;
            }
            send_data[0] = 4;
            for (int i = 0; i < 4; i++)
            {
                send_data[i + 8] = send_num[i];
            }
            handler.Send(send_data);
        }

        /// <summary>
        /// 用指定Socket向客户端发送字符串
        /// </summary>
        /// <param name="handler">Socket</param>
        /// <param name="number">数据类型代码</param>
        /// <param name="str">要发送的字符串</param>
        private static void Send(Socket handler, string number, string str)
        {
            ShowText("To " + handler.RemoteEndPoint + ": " + number + "---" + str + "\r\n");
            str = DES.EncryptDES(str, "12345678");
            byte[] data = Encoding.Unicode.GetBytes(str);
            byte[] send_data = new byte[data.Length + 12];
            byte[] send_num = Encoding.ASCII.GetBytes(number);
            long send_length = (long)data.Length + 4;
            for (int i = 0; i < 8; i++)
            {
                send_data[i] = (byte)(send_length % 256);
                send_length = send_length >> 8;
            }
            for (int i = 0; i < 4; i++)
            {
                send_data[i + 8] = send_num[i];
            }
            for (int i = 0; i < data.Length; i++)
            {
                send_data[i + 12] = data[i];
            }
            handler.Send(send_data);
        }

        /// <summary>
        /// 关闭所有连接并终止线程
        /// </summary>
        public static void Close()
        {
            for (int i = 0; i < clients.Count; i++)
            {
                Send(clients[i].WorkSock, "1005", "服务器关机维护中!");
            }
            Thread.Sleep(500);
            for (int i = 0; i < clients.Count; i++)
            {
                clients[i].WorkSock.Shutdown(SocketShutdown.Both);
                clients[i].WorkSock.Close();
            }
            clients.Count = 0;
            if (listener != null)
            {
                if (listener.Connected)
                {
                    listener.Shutdown(SocketShutdown.Both);

                } 
                listener.Close();
            }
            if (listenThread.ThreadState != ThreadState.Unstarted) listenThread.Abort();
        }

        /// <summary>
        /// 关闭指定登录名的连接并终止线程
        /// </summary>
        /// <param name="userName">登录名</param>
        public static void RemoveByUserName(string userName)
        {
            clients.RemoveByUserName(userName);
        }

        /// <summary>
        /// 关闭指定登录名的连接并终止线程
        /// </summary>
        /// <param name="userName">登录名</param>
        public static void OutLineByUserName(string userName)
        {
            clients.OutLineByUserName(userName);
            Bind();
        }

        /// <summary>
        /// 初始化连接信息表
        /// </summary>
        public static void DataTable_Load()
        {
            DataColumn dcAddress = new DataColumn("Address", Type.GetType("System.String"));
            DataColumn dcAdminName = new DataColumn("AdminName", Type.GetType("System.String"));
            dt.Columns.Add(dcAddress);
            dt.Columns.Add(dcAdminName);
        }

        private static int FindErrorLoginTimes(string userName)
        {
            int times = 0;
            DateTime currentTime = DateTime.Now;
            for (int i = 0; i < errorLogin.Count; i++)
            {
                if (currentTime < ((ErrorLogin)errorLogin[i]).Time.AddMinutes(3))
                {
                    if (((ErrorLogin)errorLogin[i]).ID == userName) times++;
                }
                else
                {
                    errorLogin.RemoveRange(i, errorLogin.Count - i);
                    return times;
                }
            }
            return times;
        }

        private static string[] GetUpdateFilePath(string version)
        {
            if (Convert.ToInt32(version) >= Properties.Settings.Default.ClientVersion)
            {
                return null;
            }
            DBConnection db = new DBConnection();
            DataTable dt = db.GetDataTable("select fileName from tb_ClientUpdate where version>" + version);
            string[] paths = new string[dt.Rows.Count];
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                paths[i] = dt.Rows[i][0].ToString();
            }
            return paths;
        }
    }

    //临时存储接收数据的类
    public class StateObject
    {
        public Socket workSocket;
        public const int BUFFER_SIZE = 4096;
        public byte[] buffer = new byte[BUFFER_SIZE];
        public string sb;
    }
}*/